using System;
using System.Collections;
using System.Text;
using Qiang.Topology.Operation;
using Qiang.Topology.GeometriesGraph;

namespace Qiang.Topology.Geometries
{
    /// <summary>
    /// Basic implementation of <c>MultiLineString</c>.
    /// </summary>    
    public class MultiLineString : GeometryCollection ,IMultiLineString
    {
        /// <summary>
        /// Represents an empty <c>MultiLineString</c>.
        /// </summary>
        public static new readonly IMultiLineString Empty = new GeometryFactory().CreateMultiLineString(null);

        /// <summary>
        /// Constructs a <c>MultiLineString</c>.
        /// </summary>
        /// <param name="lineStrings">
        /// The <c>LineString</c>s for this <c>MultiLineString</c>
        /// , or <c>null</c> or an empty array to create the empty point.
        /// Elements may be empty <c>LineString</c>s, but not <c>null</c>s.
        /// </param>
        /// <param name="precisionModel">
        /// The specification of the grid of allowable points
        /// for this <c>MultiLineString</c>.
        /// </param>
        /// <param name="SRID">
        /// The ID of the Spatial Reference System used by this
        /// <c>MultiLineString</c>.
        /// </param>
        /// <deprecated> 
        /// Use GeometryFactory instead.
        /// </deprecated>
        [Obsolete("Use GeometryFactory instead")]
        public MultiLineString(LineString[] lineStrings, PrecisionModel precisionModel, int SRID) :
            base(lineStrings, 
            new GeometryFactory(precisionModel, SRID, DefaultCoordinateSequenceFactory.Instance)){ }



        /// <param name="lineStrings">
        /// The <c>LineString</c>s for this <c>MultiLineString</c>,
        /// or <c>null</c> or an empty array to create the empty
        /// point. Elements may be empty <c>LineString</c>s,
        /// but not <c>null</c>s.
        /// </param>
        public MultiLineString(ILineString[] lineStrings, GeometryFactory factory) 
            : base(lineStrings, factory) { }        

        public override Dimensions Dimension
        {
            get
            {
                return Dimensions.Curve;
            }
        }

        public override Dimensions BoundaryDimension
        {
            get
            {
                if (IsClosed)
                    return Dimensions.False;                
                return Dimensions.Point;
            }
        }

        [Obsolete("Use reflection! GetType().FullName")]
        public override string GeometryType
        {
            get
            {
                return "MultiLineString";
            }
        }

        public virtual bool IsClosed
        {
            get
            {
                if (IsEmpty) return false;
                for (int i = 0; i < geometries.Length; i++)
                    if (!((LineString)geometries[i]).IsClosed)
                        return false;                
                return true;
            }
        }

        public override bool IsSimple
        {
            get
            {
                return (new IsSimpleOp()).IsSimple((MultiLineString)ToInternalGeometry(this));
            }
        }

        public override IGeometry Boundary
        {
            get
            {
                if(IsEmpty)
                    return Factory.CreateGeometryCollection(null);

                GeometryGraph g = new GeometryGraph(0, ToInternalGeometry(this));
                Coordinate[] pts = g.GetBoundaryPoints();
                return Factory.CreateMultiPoint(pts);
            }
        }

        public override bool EqualsExact(IGeometry other, double tolerance) 
        {
            if (!IsEquivalentClass(other)) 
                return false;            
            return base.EqualsExact(other, tolerance);
        }
    }
}
